﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using vJine.Core;
using vJine.Lua.GUI.UI;

namespace vJine.Lua.GUI {
    internal class AppStart : Application {

        public class FlowConfig {
            public string name { get; set; }
            public string alias { get; set; }
            public string path { get; set; }
            public List<FlowConfig> nodes { get; set; }
        }

        string root_context = "AppContext";
        NodeConfig luaConfig = null;
        Dictionary<string, string> Cmds = new Dictionary<string, string>();
        Dictionary<string, string> Configs = new Dictionary<string, string>();
        LuaContext luaContext = new LuaContext();

        protected virtual void parse_args() {
            string[] args = Environment.GetCommandLineArgs();
            for (int i = 1, i_max = args.Length - 1; i < i_max; ) {
                string key = args[i];
                if (key == null || !key.StartsWith("-")) {
                    i += 1; continue;
                }
                string value = args[i + 1];
                if (value == null || value.StartsWith("-")) {
                    i += 1; continue;
                }

                i += 2;
                key = key.ToLower();
                switch (key) {
                    case "-f":
                        this.Cmds.Add("-f", value);
                        break;
                    case "-c":
                        this.Cmds.Add("-c", value);
                        break;
                    case "-t":
                        this.Cmds.Add("-t", value);
                        break;
                    case "-path":
                        this.Cmds.Add("-path", value);
                        break;
                    case "-lua_path":
                        this.Cmds.Add("-lua_path", value);
                        break;
                    case "-lua_cpath":
                        this.Cmds.Add("-lua_cpath", value);
                        break;
                    default:
                        break;
                }
            }

            string Evn_Path = Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Process);
            if (this.Cmds.ContainsKey("-path")) {
                Environment.SetEnvironmentVariable("PATH", Evn_Path + ";" + this.Cmds["-path"], EnvironmentVariableTarget.Process);
            } else {
                Environment.SetEnvironmentVariable("PATH", Evn_Path + @";.\Lib", EnvironmentVariableTarget.Process);
            }

            if (this.Cmds.ContainsKey("-lua_path")) {
                luaContext.inject(@"package.path = '" + this.Cmds["-lua_path"] + "'");
            } else {
                luaContext.inject(@"package.path = '.\\?.lua'");
            }

            if (this.Cmds.ContainsKey("-lua_cpath")) {
                luaContext.inject(@"package.cpath = '" + this.Cmds["-lua_cpath"] + "'");
            } else {
                luaContext.inject(@"package.cpath = '.\\lib\\?.dll'");
            }
        }

        protected virtual void load_context() {
            luaContext.load(@"./Class.lua");

            luaContext.inject(
                "__NODE_INDEX_HELPER = {__index = function(tb, key) for _,_tb in ipairs(tb) do if _tb.name == key then return _tb end end return nil end}"
                );
            luaContext.inject(
                "__CONFIG_INDEX_HELPER = {__index = function(tb, key) for _,_tb in ipairs(tb) do if _tb.name == key then return _tb.value end end return nil end}"
                );
            if (this.Cmds.ContainsKey("-f")) {
                string script_file = this.Cmds["-f"];
                if (!File.Exists(script_file)) {
                    throw new Exception("脚本文件未找到：" + script_file);
                }
                this.luaContext.load(script_file, this.root_context);
                this.luaConfig =
                luaContext.get<NodeConfig>(this.root_context);
                this.luaConfig.set(luaContext, this.root_context);
            } else {
                this.luaContext.load("./mainConfig.lua", "mainConfig");
                List<FlowConfig> mc = this.luaContext.get<List<FlowConfig>>("mainConfig");
                this.luaConfig = new NodeConfig() { };
                this.load_context(this.luaConfig, mc, this.root_context);
            }

            luaContext.reg("on_data", new Action<string, NodeConfig>((string uri, NodeConfig data) => {
                if (data == null || data.configs == null || data.configs.Count == 0) {
                    throw new Exception(string.Format("[错误] 节点[{0}]无数据", uri));
                }

                StringBuilder sbContents = new StringBuilder();
                sbContents.Append("#H,");
                for (int i = 0, len_max = data.configs.Count - 1; i <= len_max; i++) {
                    NodeConfig data_i = data.configs[i];

                    sbContents.Append(data_i.param).Append(i < len_max ? "," : "");
                }
                sbContents.AppendLine();

                sbContents.Append("#D,");
                for (int i = 0, len_max = data.configs.Count - 1; i <= len_max; i++) {
                    NodeConfig data_i = data.configs[i];

                    string v = data_i.value == null ? "" : data_i.value.ToString();
                    sbContents.Append(v).Append(i < len_max ? "," : "");
                }
                sbContents.AppendLine();

                File.AppendAllText("./data/test_data.csv", sbContents.ToString());
            }));
        }

        void load_context(NodeConfig tConfig, List<FlowConfig> mainConfigs, string root) {

            string drl_path = Environment.CurrentDirectory + "/";
            if (mainConfigs == null) {
                return;
            }

            for (int i = 0, len = mainConfigs.Count; i < len; i++) {
                FlowConfig mConfig_i = mainConfigs[i];
                if (mConfig_i == null) {
                    continue;
                }

                string node_path = root + "." + (i + 1).ToString();

                NodeConfig config_i = null;
                if (string.IsNullOrEmpty(mConfig_i.path)) {
                    config_i = new NodeConfig();
                    this.load_context(config_i, mConfig_i.nodes, node_path);
                } else {
                    string drl_file = drl_path + mConfig_i.path;
                    if (!File.Exists(drl_file)) {
                        config_i = new NodeConfig();
                        this.load_context(config_i, mConfig_i.nodes, node_path);
                    } else {
                        this.luaContext.load(drl_file, node_path);
                        config_i = this.luaContext.get<NodeConfig>(node_path);
                    }
                }

                {
                    config_i.ignore = true;
                    config_i.name = mConfig_i.name;
                    config_i.alias = mConfig_i.alias;
                }
                config_i.set(this.luaContext, node_path);

                tConfig.Add(config_i);
            }
        }

        void load_config() {
            string config_file = "main.config";
            if (this.Cmds.ContainsKey("-c")) {
                config_file = this.Cmds["-c"];
            }
            if (File.Exists(config_file)) {
                string[] key_values = File.ReadAllLines(config_file);
                for (int i = 0, len = key_values.Length; i < len; i++) {
                    string key_value_i = key_values[i];
                    if (string.IsNullOrEmpty(key_value_i)) {
                        continue;
                    }
                    int key_index = key_value_i.IndexOf(',');
                    if (key_index < 1 || key_index >= key_value_i.Length - 1) {
                        continue;
                    }

                    this.Configs.Add(
                        key_value_i.Substring(0, key_index)
                        , key_value_i.Substring(key_index + 1));
                }
            }

            luaContext.reg("on_save", new Action<string, string>((string key, string value) => {
                if (string.IsNullOrEmpty(value)) {
                    if (this.Configs.ContainsKey(key)) {
                        this.Configs.Remove(key);
                    }
                } else {
                    if (this.Configs.ContainsKey(key)) {
                        this.Configs[key] = value;
                    } else {
                        this.Configs.Add(key, value);
                    }
                }

                StringBuilder sbConfigs = new StringBuilder();
                foreach (KeyValuePair<string, string> config in this.Configs) {
                    if (!string.IsNullOrEmpty(config.Value)) {
                        sbConfigs.AppendFormat("{0},{1}\r\n", config.Key, config.Value);
                    } else {
                        sbConfigs.AppendFormat("{0}\r\n", config.Key);
                    }
                }
                File.WriteAllText(config_file, sbConfigs.ToString());
            }));

           this.luaConfig.set_config(this.luaContext, this.Configs);
            if (this.luaConfig.Count > 0) {
                this.luaConfig[0].IsActive = true;
            } 
        }

        protected virtual void load_gui() {
            Window winMain = null;
            if (this.Cmds.ContainsKey("-f")) {
                winMain = new WinDebug().set_bound(this.luaContext, this.luaConfig);
            } else {
                winMain = new WinFlow().set_bound(this.luaContext, this.luaConfig);
            }

            if (this.Cmds.ContainsKey("-t")) {
                winMain.Title = this.Cmds["-t"];
            }
            
            this.Run(winMain);
        }

        public void load() {
            this.parse_args();

            this.load_context();

            this.load_config();

            this.load_gui();
        }

        [STAThreadAttribute()]
        public static void Main() {
            AppStart appStart = new AppStart();
            appStart.load();
        }
    }
}
